/*
 * Copyright 2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.neusoft.wenjoy.core;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.TypedStringValue;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
*
* @author vvenLi@gmail.com
*/
public class ExtensionBeanFactoryPostProcessor implements
		BeanFactoryPostProcessor, BeanNameAware{
	private String extendedBeanName;

	protected final Log logger = LogFactory.getLog(getClass());

	public void postProcessBeanFactory(
			ConfigurableListableBeanFactory beanFactory) throws BeansException {
		logger.debug(this);
		
		MutablePropertyValues pointPropertyValues = beanFactory.getBeanDefinition(extendedBeanName).getPropertyValues();
		MutablePropertyValues thisPropertyValues = beanFactory.getBeanDefinition(this.beanName).getPropertyValues();

		update(pointPropertyValues, thisPropertyValues);
	}
	
	private void update(MutablePropertyValues pointPropertyValues, MutablePropertyValues thisPropertyValues){
		PropertyValue[] thisPVs = thisPropertyValues.getPropertyValues();
		
		for(int i = 0; i < thisPVs.length; i++){			
			if( ! thisPVs[i].getName().startsWith("extendedPropertyName")){
				continue;
			}
			
			String placeholder = thisPVs[i].getName().replaceAll("extendedPropertyName", "placeholder");
			
			String extendedPropertyName;
			
			Object obj = thisPVs[i].getValue();			
			if(obj instanceof java.lang.String){
				extendedPropertyName = (String)obj;
			}else /*if(obj instanceof TypedStringValue)*/{
				extendedPropertyName = ((TypedStringValue)obj).getValue();
			}
			
			PropertyValue pv = pointPropertyValues.getPropertyValue(extendedPropertyName);
			
			PropertyValue thisPV = thisPropertyValues.getPropertyValue(placeholder);
			
			if(thisPV == null){
				continue;
			}
					
			if (pv == null) {				
				pointPropertyValues.addPropertyValue(extendedPropertyName, thisPV.getValue());
			}else{
				Object prop = pv.getValue();
				if (prop instanceof Map) {
					Map l = (Map) pv.getValue();
					l.putAll( (Map)thisPV.getValue() );
				} else if (prop instanceof Properties) {
					Properties l = (Properties) pv.getValue();
					l.putAll( (Properties)thisPV.getValue() );
				} else if (prop instanceof List) {
					List l = (List) pv.getValue();
					l.addAll((List)thisPV.getValue() );
				}else if ( prop instanceof Set) {
					Set l = (Set) pv.getValue();
					l.addAll((Set)thisPV.getValue() );
				} else {
					logger.debug("Override property definitionk {old[" + pv + "]}{new[" + thisPV + "}");
					pointPropertyValues.removePropertyValue(pv);
					pointPropertyValues.addPropertyValue(extendedPropertyName, thisPV.getValue());
				}
			}
			
		}
		
	}

	public void setExtendedBeanName(String extensionPointBeanName) {
		this.extendedBeanName = extensionPointBeanName;
	}

	private String beanName;
	public void setBeanName(String beanName) {
		this.beanName = beanName;
	}

	public void setExtendedPropertyName(String extensionPointPropertyName) {}
	public void setPlaceholder(Object placeholder) {}

	public void setExtendedPropertyName_1 (String name) {} 
	public void setExtendedPropertyName_2 (String name) {} 
	public void setExtendedPropertyName_3 (String name) {} 
	public void setExtendedPropertyName_4 (String name) {} 
	public void setExtendedPropertyName_5 (String name) {} 
	public void setExtendedPropertyName_6 (String name) {} 
	public void setExtendedPropertyName_7 (String name) {} 
	public void setExtendedPropertyName_8 (String name) {} 
	public void setExtendedPropertyName_9 (String name) {} 
	public void setExtendedPropertyName_10(String name) {} 
	public void setExtendedPropertyName_11(String name) {} 
	public void setExtendedPropertyName_12(String name) {} 
	public void setExtendedPropertyName_13(String name) {} 
	public void setExtendedPropertyName_14(String name) {} 
	public void setExtendedPropertyName_15(String name) {} 
	public void setExtendedPropertyName_16(String name) {} 
	public void setExtendedPropertyName_17(String name) {} 
	public void setExtendedPropertyName_18(String name) {} 
	public void setExtendedPropertyName_19(String name) {} 
	public void setExtendedPropertyName_20(String name) {} 
	public void setExtendedPropertyName_21(String name) {} 
	public void setExtendedPropertyName_22(String name) {} 
	public void setExtendedPropertyName_23(String name) {} 
	public void setExtendedPropertyName_24(String name) {} 
	public void setExtendedPropertyName_25(String name) {} 
	public void setExtendedPropertyName_26(String name) {} 
	public void setExtendedPropertyName_27(String name) {} 
	public void setExtendedPropertyName_28(String name) {}
	public void setExtendedPropertyName_29(String name) {}
	public void setExtendedPropertyName_30(String name) {}	
	public void setPlaceholder_1 (Object ph) {}
	public void setPlaceholder_2 (Object ph) {}
	public void setPlaceholder_3 (Object ph) {}
	public void setPlaceholder_4 (Object ph) {}
	public void setPlaceholder_5 (Object ph) {}
	public void setPlaceholder_6 (Object ph) {}
	public void setPlaceholder_7 (Object ph) {}
	public void setPlaceholder_8 (Object ph) {}
	public void setPlaceholder_9 (Object ph) {}
	public void setPlaceholder_10(Object ph) {}
	public void setPlaceholder_11(Object ph) {}
	public void setPlaceholder_12(Object ph) {}
	public void setPlaceholder_13(Object ph) {}
	public void setPlaceholder_14(Object ph) {}
	public void setPlaceholder_15(Object ph) {}
	public void setPlaceholder_16(Object ph) {}
	public void setPlaceholder_17(Object ph) {}
	public void setPlaceholder_18(Object ph) {}
	public void setPlaceholder_19(Object ph) {}
	public void setPlaceholder_20(Object ph) {}
	public void setPlaceholder_21(Object ph) {}
	public void setPlaceholder_22(Object ph) {}
	public void setPlaceholder_23(Object ph) {}
	public void setPlaceholder_24(Object ph) {}
	public void setPlaceholder_25(Object ph) {}
	public void setPlaceholder_26(Object ph) {}
	public void setPlaceholder_27(Object ph) {}
	public void setPlaceholder_28(Object ph) {}
	public void setPlaceholder_29(Object ph) {}
	public void setPlaceholder_30(Object ph) {}

}
